import { StringUtil } from './StringUtil'

export const JsonUtil = {
  isJson: (obj) => {
    if (StringUtil.isString(obj)) {
      try {
        const jsonObj = JSON.parse(obj)

        return jsonObj && StringUtil.isObject(jsonObj)
      } catch {
        return false
      }
    }

    return false
  },
  /**
   * 对象置空
   * @param obj
   * @returns {*}
   */
  resetObject (obj, isFilterReset) {
    if (!StringUtil.isObject(obj)) {
      return console.error('置空参数需要是Object，如：{name:"test", age: 18}')
    }

    const filter = StringUtil.isString(isFilterReset) || StringUtil.isArray(isFilterReset)
    if (isFilterReset && !filter) {
     return console.error('过滤条件参数必须是字符串或者字符串数组，如："name"或者["name", "age"]')
    }

    for (const item in obj) {
      const pages = item === 'pageNum' || item === 'pageSize' || item === 'total'
      const isFilter = isFilterReset && isFilterReset.includes(item)
      if (isFilter || pages) {
        continue
      }

      obj[item] = null
    }

    return obj
  },
  /**
   * Deep copy the given object considering circular structure.
   * This function caches all nested objects and its copies.
   * If it detects circular structure, use cached copy to avoid infinite loop.
   *
   * @param {*} obj
   * @param {Array<Object>} cache
   * @return {*}
   */
  deepCopy (obj, cache = []) {
    if (StringUtil.isEmpty(obj) || !StringUtil.isObject(obj)) {
      return obj
    }

    const hit = find(cache, c => c.original === obj)
    if (hit) {
      return hit.copy
    }
    const copy = StringUtil.isArray(obj) ? [] : {}
    cache.push({ original: obj, copy })
    Object.keys(obj).forEach(key => {
      copy[key] = this.deepCopy(obj[key], cache)
    })

    return copy
  },
  /**
   * 对象合并
   * @param {Object} target
   * @param {Object} source
   * @returns {Object}
   */
  assign (target, source) {
    if (!StringUtil.isObject(target)) {
      return console.error('第一个参数类型必须是Object，如：{name:"test", age: 18}')
    }

    if (!StringUtil.isObject(source)) {
      return console.error('第二个参数类型必须是Object，如：{name:"test", age: 18}')
    }

    return { ...target, ...source }
  },
  /**
   * 数据合并
   * @param source
   * @param target
   * @return {*}
   */
  mergeRecursive (source, target) {
    for (const p in target) {
      try {
        if (target[p].constructor === Object) {
          source[p] = this.mergeRecursive(source[p], target[p])
        } else {
          source[p] = target[p]
        }
      } catch (e) {
        source[p] = target[p]
      }
    }

    return source
  },
  /**
   * Merges two objects, giving the last one precedence
   * @param {Object} target
   * @param {(Object|Array)} source
   * @returns {Object}
   */
  objectMerge (target, source) {
    if (!StringUtil.isObject(target)) {
      target = {}
    }

    if (StringUtil.isArray(source)) {
      return source.slice()
    }

    Object.keys(source).forEach(property => {
      const sourceProperty = source[property]
      if (StringUtil.isObject(sourceProperty)) {
        target[property] = this.objectMerge(target[property], sourceProperty)
      } else {
        target[property] = sourceProperty
      }
    })

    return target
  },
  /**
   * 解析JSON（将json字符串 转换成json对象）
   * @param json
   * @returns {*}
   */
  parseJson (json) {
    return JsonUtil.isJson(json) ? JSON.parse(json) : json
  },
  /**
   * JSON数据序列化
   * @returns {trim}
   */
  stringify (obj) {
    return JSON.stringify(obj).trim()
  },
  // 表单重置, el-form-item中的prop需必填
  resetForm (refName) {
    if (this.$refs[refName]) {
      this.$refs[refName].resetFields()
    }
  },

  // 表单指定字段清除
  clearForm (form, args) {
    if (!StringUtil.isObject(form)) {
      return console.error('参数输入错误, 第一个参数是表单对象')
    }

    if (!StringUtil.isArray(args)) {
      // eslint-disable-next-line no-throw-literal
      throw '参数输入错误, 第二个参数是表单字段数组，[字段1, 字段2, ...]'
    }

    if (args && args.length > 0) {
      for (const item of args) {
        form[item] = null
      }
    }

    return form
  },
  /**
   * 将json数组对象拼接成请求参数key1=value1&key2=value2&...样式的字符串
   * @param {Object} json
   * @returns {Array}
   */
  serializeUrlParam (json) {
    if (!json) return ''

    return Object.keys(json).map(key => json[key] ? encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) : '').join('&')
  },
  /**
   * 将请求参数key1=value1&key2=value2&...转成json数组对象
   * @param {string} url
   * @returns {Object}
   */
  deserializeUrlParam (url) {
    const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')

    if (!search) {
      return {}
    }

    const obj = {}
    const searchArr = search.split('&')
    searchArr.forEach(v => {
      if (v.includes('=')) {
        const param = v.split('=')
        obj[param[0]] = param[1]
      }
    })

    return obj
  }
}
